//
//  TJCountdownHandler.m
//  HoHo
//
//  Created by xiatiejun on 2021/8/1.
//  Copyright © 2021 xiatiejun. All rights reserved.
//

#import "TJTimer.h"

@interface TJTimer()

@property (nonatomic, strong) dispatch_source_t sourceTimer;

@end



@implementation TJTimer


+ (instancetype)timer {
    return [[TJTimer alloc] init];
}

- (void)cancel {
    if (_sourceTimer) {
        dispatch_source_cancel(_sourceTimer);
        _sourceTimer = nil;
    }
}

//毫秒级别 1s = 1000ms
- (void)start:(int)interval ongoing:(void (^)(void))ongoing {
    
    if (_sourceTimer) {
        dispatch_source_cancel(_sourceTimer);
    }
 
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval * NSEC_PER_MSEC, 0 * NSEC_PER_MSEC);
    dispatch_source_set_event_handler(timer, ^{
        if (ongoing) {
            ongoing();
        }
    });
    
    dispatch_resume(timer);
    _sourceTimer = timer;
}

- (void)start:(int)interval target:(id)target action:(SEL)action {
    
    if (_sourceTimer) {
        dispatch_source_cancel(_sourceTimer);
    }
 
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval * NSEC_PER_MSEC, 0 * NSEC_PER_MSEC);
    dispatch_source_set_event_handler(timer, ^{
        if ([target respondsToSelector:action]) {
            [target performSelector:action];
        }
    });
    
    dispatch_resume(timer);
    _sourceTimer = timer;
}

- (void)after:(int)interval execute:(void (^)(void))execute {
    
    if (_sourceTimer) {
        dispatch_source_cancel(_sourceTimer);
    }
 
    __block NSInteger second = interval;

    TJWeakify(self)
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        
        if (second <= 0) {
            dispatch_source_cancel(weakself.sourceTimer);
            weakself.sourceTimer = nil;
            if (execute) {
                execute();
            }
        }
        
        second--;
    });
    
    dispatch_resume(timer);
    _sourceTimer = timer;
}

- (void)start_MSEC:(int)interval ongoing:(void (^)(void))ongoing {
    
    if (_sourceTimer) {
        dispatch_source_cancel(_sourceTimer);
    }
 
    
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval * NSEC_PER_MSEC, 0 * NSEC_PER_MSEC);
    dispatch_source_set_event_handler(timer, ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (ongoing) {
                ongoing();
            }
        });
    });
    
    dispatch_resume(timer);
    _sourceTimer = timer;
}

- (void)start_SEC:(int)interval ongoing:(void (^)(void))ongoing {
    
    if (_sourceTimer) {
        dispatch_source_cancel(_sourceTimer);
    }
 
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (ongoing) {
                ongoing();
            }
        });
    });
    
    dispatch_resume(timer);
    _sourceTimer = timer;
}

- (void)start:(NSInteger)totalTime countdownOngoing:(void (^)(NSInteger time))countdownOngoing countdownEnd:(void (^)(void))countdownEnd {
    
    if (_sourceTimer) {
        dispatch_source_cancel(_sourceTimer);
    }
    
    __block NSInteger second = totalTime;
    
    TJWeakify(self)
    
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        
        second--;
        
        if (second <= 0) {
            dispatch_source_cancel(timer);
            weakself.sourceTimer = nil;
            dispatch_async(dispatch_get_main_queue(), ^{
                if (countdownEnd) {
                    countdownEnd();
                }
            });
            
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (countdownOngoing) {
                    countdownOngoing(second);
                }
            });
            
        }
    });
    
    dispatch_resume(timer);
    _sourceTimer = timer;
}

- (void)dealloc {
    if (_sourceTimer) {
        dispatch_source_cancel(_sourceTimer);
        _sourceTimer = nil;
    }
}

@end
